package com.cloud.easy.im.netty.config;

import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.socket.ServerSocketChannelConfig;

import java.net.SocketException;
import java.nio.channels.DatagramChannel;

/**
 * 仿照TCP的“形”实现了一个UDP的服务端Channel配置类。
 *
 * 因为Netty4中，对于ServerBootstrap来说为了灵活应对各种场景， 有很多参数可供设置，所以从设计模式的角度讲，
 * 就把这部分配置 独立成了遵从Builder设计模式的封装类，让ServerBootstrap的 API显的更优雅。
 */
public class UDPServerChannelConfig extends DefaultChannelConfig implements ServerSocketChannelConfig
{
	/** UDP NIO channel通道实例 **/
	private final DatagramChannel datagramChannel;

	public UDPServerChannelConfig(Channel channel, DatagramChannel datagramChannel)
	{
		super(channel);
		this.datagramChannel = datagramChannel;
		
		setRecvByteBufAllocator(new FixedRecvByteBufAllocator(2048));
	}

	/**
	 * backlog参数主要用于TCP场景下，是内核为此套接口 排队的最大连接个数，UDP时给1就行了，因为没意义。
	 * @return
	 */
	public int getBacklog()
	{
		return 1;
	}

	/**
	 * backlog参数对于UDP来说无意义，它主要用于TCP场景下，是内核为此套接口 排队的最大连接个数，因而本方法只是个空方法。
	 * @param backlog
	 * @return
	 */
	public ServerSocketChannelConfig setBacklog(int backlog)
	{
		return this;
	}

	/**
	 * connectTimeoutMillis对于UDP来说无意义，因而本方法只是个空方法。
	 * @param timeout
	 * @return
	 */
	public ServerSocketChannelConfig setConnectTimeoutMillis(int timeout)
	{
		return this;
	}

	/**
	 * 本方法对于UDP来说无意义，因而本方法只是个空方法。
	 * @param arg0
	 * @param arg1
	 * @param arg2
	 * @return
	 */
	public ServerSocketChannelConfig setPerformancePreferences(int arg0, int arg1, int arg2)
	{
		return this;
	}

	public ServerSocketChannelConfig setAllocator(ByteBufAllocator alloc)
	{
		super.setAllocator(alloc);
		return this;
	}

	public ServerSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator alloc)
	{
		super.setRecvByteBufAllocator(alloc);
		return this;
	}

	public ServerSocketChannelConfig setAutoRead(boolean autoread)
	{
		super.setAutoRead(true);
		return this;
	}

	@Deprecated
	public ServerSocketChannelConfig setMaxMessagesPerRead(int n)
	{
		super.setMaxMessagesPerRead(n);
		return this;
	}

	public ServerSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator est)
	{
		super.setMessageSizeEstimator(est);
		return this;
	}

	public ServerSocketChannelConfig setWriteSpinCount(int spincount)
	{
		super.setWriteSpinCount(spincount);
		return this;
	}

	public ServerSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark)
	{
		return (ServerSocketChannelConfig) super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
	}

	public ServerSocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark)
	{
		return (ServerSocketChannelConfig) super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
	}

	public ServerSocketChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark)
	{
		return (ServerSocketChannelConfig) super.setWriteBufferWaterMark(writeBufferWaterMark);
	}

	public int getReceiveBufferSize()
	{
		try
		{
			return datagramChannel.socket().getReceiveBufferSize();
		} 
		catch (SocketException ex)
		{
			throw new ChannelException(ex);
		}
	}

	public ServerSocketChannelConfig setReceiveBufferSize(int size)
	{
		try
		{
			datagramChannel.socket().setReceiveBufferSize(size);
		} 
		catch (SocketException ex) 
		{
			throw new ChannelException(ex);
		}
		return this;
	}

	public boolean isReuseAddress()
	{
		try
		{
			return datagramChannel.socket().getReuseAddress();
		}
		catch (SocketException ex) 
		{
			throw new ChannelException(ex);
		}
	}

	public ServerSocketChannelConfig setReuseAddress(boolean reuseaddr)
	{
		try 
		{
			datagramChannel.socket().setReuseAddress(true);
		} 
		catch (SocketException ex) 
		{
			throw new ChannelException(ex);
		}
		return this;
	}
}
